/*************************************************************************
	> 文件名: echoServer.cc
	> 作者: 马海城
	> 邮箱: hchma@outlook.com
	> 创建日期: 2016年05月20日 星期五 11时00分55秒
 ************************************************************************/

#include<iostream>
#include<utility>
#include<cassert>
#include<muduo/net/EventLoop.h>
#include<muduo/net/TcpServer.h>
#include<muduo/base/Logging.h>

using namespace std;
using namespace std::placeholders;
using namespace muduo;
using namespace muduo::net;

class EchoServer
{
public:
    EchoServer(EventLoop *loop, const InetAddress &listenAddr) : 
                echoServer_(loop, listenAddr, "echo server"), loop_(loop), clientCount(0)
    {
        assert(loop_ != nullptr);
        echoServer_.setConnectionCallback(bind(&EchoServer::onConnection, this, _1));
        echoServer_.setMessageCallback(bind(&EchoServer::onMessage, this, _1, _2, _3));
    }
    // noncopyable
    EchoServer(const EchoServer &) = delete;
    EchoServer& operator=(const EchoServer &) = delete;
    
    // can not create EchoServer on heap
    void* operator new(size_t) = delete;

    void start()
    {
        echoServer_.start();
    }
private:
    void onConnection(const TcpConnectionPtr &conn)
    {
        if (conn->connected())
        {
            conn->send("Hello, my dear client. Welcome to the echo server.\ntype \"exit\" to exit...");
        }
        else
        {
            LOG_INFO << "client: " << ++clientCount << " closed.\n";
        }
    }
    void onMessage(const TcpConnectionPtr &conn, Buffer *buf, Timestamp time)
    {
        muduo::string msg(buf->retrieveAllAsString());
        
        if (msg == "exit")
        {
            conn->send("Bye-Bye\n");
        }
        else
        {
            conn->send(msg);
        }
    }
private:
    TcpServer echoServer_;
    EventLoop *loop_;
    int clientCount;
};

int main()
{
    EventLoop loop;
    InetAddress listenAddr(8888);
    EchoServer server(&loop, listenAddr);
    server.start();
    loop.loop();
}
